#include<iostream>
#include<cstring>
using namespace std;
const int M = 110;
const int N = 5e4 + 10;
int f[N];
int p[N], c[N];
int n, m;
int main()
{
	cin >> n >> m;
	for (int i = 1;i <= n;i++)
	{
		cin >> p[i] >> c[i];
	}
	////因为是最小花费，所以所有非法的位置都给到正无穷
	////有没有非法的位置就看第一行就行，第一行前0个找，最小价值不为0，那肯定有非法的，那就得memset
	//memset(f, 0x3f,sizeof(f));
	//f[0][0] = 0;
	//for (int i = 1;i <= n;i++)
	//{
	//	for (int j = 0;j <= m;j++)
	//	{
	//		//一般方案类你就直接+=就行了，花费类问题得分情况讨论
	//		//而且一般第二个表达式里面有+一个数的一般不用把第一个位置给到1，因为他不会出现所有数都等于0的情况
	//		//这个不用判断大小了，如果超了直接去0，也就是至少为0的那个值就可以了
	//		f[i][j] =min(f[i-1][j], f[i][j - p[i] <= 0 ? 0 : j - p[i]] + c[i]);
	//		
	//	}
	//}
	//cout << f[n][m] << endl;
	//因为是最小花费，所以所有非法的位置都给到正无穷
	//有没有非法的位置就看第一行就行，第一行前0个找，最小价值不为0，那肯定有非法的，那就得memset
	memset(f, 0x3f, sizeof(f));
	f[0] = 0;
	for (int i = 1;i <= n;i++)
	{
		for (int j = 0;j <= m;j++)
		{
			//一般方案类你就直接+=就行了，花费类问题得分情况讨论
			//而且一般第二个表达式里面有+一个数的一般不用把第一个位置给到1，因为他不会出现所有数都等于0的情况
			//这个不用判断大小了，如果超了直接去0，也就是至少为0的那个值就可以了
			f[j] = min(f[j], f[j - p[i] <= 0 ? 0 : j - p[i]] + c[i]);

		}
	}
	cout << f[m] << endl;
	return 0;

}